#ifndef RECTEST_H
#define RECTEST_H

#include "Recetario.h"
#include <iostream>
#include <string>

/**
 * Esta clase realiza los test de Recetario.
*/
class RecetarioTest
{
	public:
	RecetarioTest();
        void StartTest ();
        void Result ();

	protected:
    	
		bool RecetarioCrear();
		bool RecetarioAgregarIngrediente();
		bool RecetarioAgregarPlato();
		bool RecetarioIngredientesNecesariosPlato();
		bool RecetarioIngredientesNecesariosPedido();
		bool RecetarioAsignacion();

	private:
		int ok;
		int error;

		
		Recetario *r1;
		Recetario *r2;
		Recetario *r3;

};


RecetarioTest::RecetarioTest() {
	ok = 0;
	error = 0;
	r1 = new Recetario ();
	r2 = new Recetario ();
	r3 = new Recetario ();


}
void RecetarioTest::StartTest(){

	if(RecetarioCrear()){
		ok++;
	}else{
		error++;
	}
	
	if(RecetarioAgregarIngrediente()){
		ok++;
	}else{
		error++;
	}
	if(RecetarioAgregarPlato()){
		ok++;
	}else{
		error++;
	}

	if(RecetarioIngredientesNecesariosPlato()){
		ok++;
	}else{
		error++;
	}

	if(RecetarioIngredientesNecesariosPedido()){
		ok++;
	}else{
		error++;
	}
	if(RecetarioAsignacion()){
		ok++;
	}else{
		error++;
	}

	delete r1;
	delete r2;
	delete r3;

}
void RecetarioTest::Result (){
	cout << "RECETARIO test Ok:" << ok << endl;
	cout << "RECETARIO test cont error:" << error << endl;
};

bool RecetarioTest::RecetarioCrear(){
	cout << "RECETARIO::creo r1 r2 r3:" << endl;
	if(!r1->ingredientes().vacio()){
		cout << "REC::r1 tiene basura:" << endl;
		return false;
	}
	if(!r2->ingredientes().vacio()){
		cout << "REC::r2 tiene basura:" << endl;
		return false;
	}
	if(!r3->ingredientes().vacio()){
		cout << "REC::r2 tiene basura:" << endl;
		return false;
	}

	return true;


}

bool RecetarioTest::RecetarioAgregarIngrediente() {

	cout << "RECETARIO::agrego los ingredientes \"aceite\", \"mayonesa\", \"vinagre\", \"aceitunas\" a r1:" << endl;

	r1 -> agregarIngrediente("aceite");
	r1 -> agregarIngrediente("mayonesa");
	r1 -> agregarIngrediente("vinagre");
	r1 -> agregarIngrediente("aceitunas");	
	r1 -> agregarIngrediente("vino");	

	if(!r1->ingredientes().pertenece("aceite")){
		cout << "REC::En r1 no se encontró correctamente el aceite agregado:" << endl;
		return false;
	}
	if(!r1->ingredientes().pertenece("mayonesa")){
		cout << "REC::En r1 no se encontró correctamente la mayonesa agregada:" << endl;
		return false;
	}
	if(!r1->ingredientes().pertenece("vinagre")){
		cout << "REC::En r1 no se encontró correctamente el vinagre agregado:" << endl;
		return false;
	}
	if(!r1->ingredientes().pertenece("aceitunas")){
		cout << "REC::En r1 no se encontraron correctamente las aceitunas agregadas:" << endl;
		return false;
	}

	if(!r1->ingredientes().pertenece("vino")){
		cout << "REC::En r1 no se encontraro el vino agregado:" << endl;
		return false;
	}
	return true;
}

bool RecetarioTest::RecetarioAgregarPlato() {
	cout << "Creo un plato con los siguientes ingredientes (plato1):" << endl;
	MConj plato1;
	plato1.mAgregarN("aceite", 5);
	plato1.mAgregarN("aceite", 5);
	plato1.mAgregarN("vino", 4);
	plato1.mAgregarN("vinagre", 3);
	cout << plato1 << "\n";
	cout << "Y otro con los siguientes (plato2):" << endl;
	MConj plato2;
	plato2.mAgregarN("mayonesa", 5);
	plato2.mAgregarN("vino", 5);
	plato2.mAgregarN("aceitunas", 4);
	plato2.mAgregarN("vinagre", 7);
	cout << plato2 << "\n";
	cout << "Los agrego al recetario r2 \n";
	r2 -> agregarPlato("platouno", plato1);
	r2 -> agregarPlato("platodos", plato2);
	
	cout << "El r2 no tiene que haber incorporado los platos porque no tenía ningún ingrediente incorporado: \n";
	if(!r1->platos().vacio()){
		cout << "ERROR!\n" << endl;
		return false;
	}
	else
		cout << "OK!\n";
	cout << "Agrego los ingredientes necesarios para que se pueda admitir el plato1 pero no el plato2. \n";
	r2 -> agregarIngrediente("aceite");
	r2 -> agregarIngrediente("vino");
	r2 -> agregarIngrediente("vinagre");
	cout << "Ahora en r2 tiene que estar el plato1 pero no el plato2: \n";
	r2 -> agregarPlato("platouno", plato1);
	r2 -> agregarPlato("platodos", plato2);
	if(r2->platos().pertenece("platouno") && !r2->platos().pertenece("platodos"))
		cout << "OK!\n" << endl;
	else {
		cout << "ERROR!\n";
		return false;
	}
	cout << "Agrego los ingredientes necesarios para que se pueda incorporar el plato2. \n";
	r2 -> agregarIngrediente("mayonesa");
	r2 -> agregarIngrediente("aceitunas");
	cout << "Ahora en r2 tiene que estar el plato1 y plato2: \n";
	r2 -> agregarPlato("platouno", plato1);
	r2 -> agregarPlato("platodos", plato2);
	if(r2->platos().pertenece("platouno") && r2->platos().pertenece("platodos"))
		cout << "OK!\n" << endl;
	else {
		cout << "ERROR!\n";
		return false;
	}
	cout << "Ahora los platos del recetario son: \n";
	cout << r2 -> platos() << "\n";
	
	cout << "Agrego el plato1 al r1: \n";
	r1 -> agregarPlato("platouno", plato1);
	if(r1 -> platos().pertenece("platouno"))
		cout << "OK!\n" << endl;
	else {
		cout << "ERROR!\n";
		return false;
	}	
	return true;
}

bool RecetarioTest::RecetarioIngredientesNecesariosPlato() {
	cout << "Creo un plato con los siguientes ingredientes (plato3):" << endl;
	MConj plato3;
	plato3.mAgregarN("aceite", 1);
	plato3.mAgregarN("mayonesa", 5);
	cout << plato3 << "\n";
	cout << "Y otro con los siguientes (plato4):" << endl;
	MConj plato4;
	plato4.mAgregarN("mayonesa", 5);
	plato4.mAgregarN("vino", 5);
	plato4.mAgregarN("aceitunas", 4);
	plato4.mAgregarN("vinagre", 7);
	cout << plato4 << "\n";
	cout << "Y otro con los siguientes (plato5):" << endl;
	MConj plato5;
	plato5.mAgregarN("aceitunas", 3);
	plato5.mAgregarN("aceite", 5);
	cout << plato5 << "\n";

	cout << "Los agrego al recetario r2 \n";
	r2 -> agregarPlato("platotres", plato3);
	r2 -> agregarPlato("platocuatro", plato4);
	r2 -> agregarPlato("platocinco", plato5);
	
	cout << "Los ingredientes necesarios para el plato3 son: \n";
	cout << r2 -> ingredientesNecesarios("platotres") << "\n";


	cout << "Los ingredientes necesarios para el plato4 son: \n";
	cout << r2 -> ingredientesNecesarios("platocuatro") << "\n";

	cout << "Los ingredientes necesarios para el plato5 son: \n";
	cout << r2 -> ingredientesNecesarios("platocinco") << "\n";

	cout << "Son necesarias aceitunas para el plato5: \n"; 
	if(r2 -> ingredientesNecesarios("platocinco").pertenece("aceitunas"))
		cout << "OK!\n" << endl;
	else {
		cout << "ERROR!\n";
		return false;
	}	

	cout << "No son necesarias aceitunas para el plato3: \n"; 
	if(r2 -> ingredientesNecesarios("platotres").pertenece("aceitunas")){
		cout << "ERROR!\n" << endl;
		return false;
	}
	else 
		cout << "OK!\n";
	cout << "La cantidad necesaria de aceite para el plato3 es: 1 \n"; 
	if(!r2 -> cantidadNecesaria("platotres", "aceite") == 1){
		cout << "NO!\n" << endl;
		return false;
	}
	else 
		cout << "SI!\n";
	
	cout << "La cantidad necesaria de aceite para el plato5 es: 3 \n"; 
	if(!r2 -> cantidadNecesaria("platocinco", "aceite") == 1){
		cout << "SI!\n" << endl;
		return false;
	}
	else 
		cout << "NO!\n";
	cout << "La cantidad necesaria de aceite para el plato5 es: "; 
	cout << r2 -> cantidadNecesaria("platocinco", "aceite");
	cout << endl;

	return true;


}

bool RecetarioTest::RecetarioIngredientesNecesariosPedido() {
	MConj plato1;
	plato1.mAgregarN("aceite", 5);
	plato1.mAgregarN("aceite", 5);
	plato1.mAgregarN("vino", 4);
	plato1.mAgregarN("vinagre", 3);
	MConj plato2;
	plato2.mAgregarN("mayonesa", 5);
	plato2.mAgregarN("vino", 5);
	plato2.mAgregarN("aceitunas", 4);
	plato2.mAgregarN("vinagre", 7);
	MConj plato3;
	plato3.mAgregarN("aceite", 1);
	plato3.mAgregarN("mayonesa", 5);
	MConj plato4;
	plato4.mAgregarN("mayonesa", 5);
	plato4.mAgregarN("vino", 5);
	plato4.mAgregarN("aceitunas", 4);
	plato4.mAgregarN("vinagre", 7);
	MConj plato5;
	plato5.mAgregarN("aceitunas", 3);
	plato5.mAgregarN("aceite", 5);

	cout << "Agrego a r1 todos los platos. \n";
	r1 -> agregarPlato("platouno", plato1);
	r1 -> agregarPlato("platodos", plato2);
	r1 -> agregarPlato("platotres", plato3);
	r1 -> agregarPlato("platocuatro", plato4);
	r1 -> agregarPlato("platocinco", plato5);
	cout << "Los platos son: \n";
	cout << r1 -> platos() << "\n";
	cout << "Creo un pedido de 2 platos1, 3 platos2 y 4 platos5. \n";
	MConj pedido;
	pedido.mAgregarN("platouno", 2);
	pedido.mAgregarN("platodos", 3);
	pedido.mAgregarN("platocinco", 4);
	cout << "Los ingredientes necesarios para el pedido son: \n";
	cout << r1 -> ingredientesNecesariosPedido(pedido) << "\n";
	cout << "Y en la siguiente cantidad: \n";
	cout << r1 -> ingredientesPedido(pedido) << "\n";
	cout << "Esto es así? ";
 		string aux;
	MConj m =  r1 -> ingredientesPedido(pedido);
	IteradorMConj it(m);
	int cNecesaria = 0;
	while (it.tieneProximo()) {
		aux = it.proximo();
		cNecesaria = 2*(r1 -> cantidadNecesaria("platouno", aux)) +  3*(r1 -> cantidadNecesaria("platodos", aux)) + 4*(r1 -> cantidadNecesaria("platocinco", aux));
		if (r1 -> ingredientesPedido(pedido).mCantidad(aux) != cNecesaria){
			cout << "NO!";
			return false;
		}

	}
	cout << "SI!\n";	
	return true;


}

bool RecetarioTest::RecetarioAsignacion() {

	cout << "El r1 tiene los siguientes platos: \n";
	cout << r1 -> platos() << "\n";

	cout << "y los siguientes ingredientes: \n";
	cout << r1 -> ingredientes() << "\n";

	cout << "r3 esta vacio? \n";
	if (r3 -> platos().vacio() && r3 -> ingredientes().vacio())
		cout << "SI! \n";
	else {
		cout << "NO! \n";
		return false;
	}
	cout << "Ahora le asigno por copia a r1. \n";
	*r3 = *r1;
	cout << "r3 esta vacio ahora? \n";
	if (!(r3 -> platos().vacio() && r3 -> ingredientes().vacio()))
		cout << "NO! \n";
	else {
		cout << "SI! \n";
		return false;
	}
	cout << "Estos son los platos que tiene ahora: \n";
	cout << r3 -> platos() << "\n";
	cout << "Y los ingredientes: \n";
	cout << r3 -> ingredientes() << "\n";
	cout << "Ahora le agrego un ingrediente. \n";
	r3 -> agregarIngrediente("ingredientesecreto");
	cout << "Estos son los ingredientes que tiene ahora: \n";
	cout << r3 -> ingredientes() << "\n";
	cout << "Y estos son los ingredientes que tiene ahora r1: \n";
	cout << r1 -> ingredientes() << "\n";
	cout << "r3 tiene el ingrediente secreto? \n";
	if (r3 -> ingredientes().pertenece("ingredientesecreto"))
		cout << "SI!\n";
	else {
		cout << "NO!\n";
		return false;
	}
	cout << "r1 tiene el ingrediente secreto? \n";
	if (!(r1 -> ingredientes().pertenece("ingredientesecreto")))
		cout << "NO!\n";
	else {
		cout << "SI!\n";
		return false;
	}
	return true;
}
#endif

